#pragma once

// base camera implementation
//forward declare
class VxIrrBase;


// enumerate camera modes
enum ECameraMode
{
	eCameraModeUser			= 0,	// do nothing.. even in update.. user program will do everthing directly
	eCameraModeDoll			= 1,	// doll view mode
	eCameraModeOrbit		= 2,	// orbit target mode
	eCameraModeFps			= 3,	// first person shooter mode

	eMaxCameraMode,	// must be last
};


class CameraBase
{
public:
	//=== vars ===//
	VxIrrBase *						m_poIrrBase;			// game manager
	S32								m_s32EntId;				// id of this cam
	S32								m_s32OwnerId;			// owner of this cam
	ECameraMode						m_eCameraMode;			// camera mode
	irr::scene::ICameraSceneNode *	m_poCamNode;			// camera scene node

	irr::scene::ISceneNode *		m_poSelectedNode;		// selected node
	irr::core::vector3df 			m_v3fViewCamTarget;		// camera target position
	int								m_iScnSizeX;			// screen width
	int								m_iScnSizeY;			// screen height

	//=== orbit cam vars ===//
	irr::core::matrix4				m_mat4OrbitTransform;	// used for yaw pitch orbit calculation
	irr::core::vector3df			m_v3fDirection;			// direction camera is pointed 
	irr::core::vector3df			m_v3fPreviousPosition;	// previous position of camera
	irr::core::vector3df			m_v3fPreviousLookAt;	// previous point camera was pointed at
	F32								m_f32Yaw;				// angle of rotation around target
	F32								m_f32Pitch;				// angle camera is looking down 
	F32								m_f32MaxDistance;		// max distance camera from target
	F32								m_f32CurDistance;		// current distance camera from target

	//=== other ===//
	BOOL							m_bCamChanged;			// if true cam has changed direction or position

	//=== constructor ===//
	CameraBase( VxIrrBase * poMgr, S32 s32Id = 0, S32 s32OwnerId = 0 );
	//==== destructor ===//
	virtual ~CameraBase();

	//=== properties ===//
	S32					GetEntId() const								{ return m_s32EntId; }
	void				SetEntId( S32 s32Id )							{ m_s32EntId = s32Id; }
	S32					GetOwnerId() const								{ return m_s32OwnerId; }
	void				SetOwnerId( S32 s32OwnerId )					{ m_s32OwnerId = s32OwnerId; }

	ECameraMode			GetCameraMode() const							{ return m_eCameraMode; }
	void				SetCameraMode( ECameraMode eCamMode )			{ m_eCameraMode = eCamMode; }
	irr::scene::ICameraSceneNode *	GetCameraSceneNode( void)			{ return m_poCamNode; }
	void							SetCameraSceneNode( irr::scene::ICameraSceneNode * poCamNode )	{ m_poCamNode = poCamNode; }

	//=== cam position properties ===//
	// set position of camera
	irr::core::vector3df	GetIrrPosition() const	 							{ return m_poCamNode->getPosition(); }
	// get position of camera
	void					SetIrrPosition( const irr::core::vector3df& v3fPos ){ m_poCamNode->setPosition( v3fPos ); }
	// set target camera is looking at
	void					SetIrrTarget( const irr::core::vector3df& v3fPos )	{ m_poCamNode->setTarget( v3fPos ); }

	//=== orbit cam properties ===//
	const irr::core::vector3df &	GetDirection() const				{ return m_v3fDirection; }
	void				SetRotation( F32 f32Yaw, F32 f32Pitch )			{ this->m_f32Yaw = f32Yaw, this->m_f32Pitch = f32Pitch; }
	F32					GetDistance( void )								{ return m_f32MaxDistance; }
	void				SetDistance( F32 f32Distance )					{ m_f32MaxDistance = f32Distance; }
	F32					GetYaw( void ) const							{ return m_f32Yaw; }
	void				SetYaw( F32 f32Value )							{ m_f32Yaw = f32Value; }
	F32					GetPitch( void ) const							{ return m_f32Pitch; }
	void				SetPitch( F32 f32Value)							{ m_f32Pitch = f32Value; }



	//=== implementation ===//
	//!	create and startup camera
	virtual RCODE Startup( VxIrrBase * pgIrrBase );
	//!	shutdown camera
	virtual void Shutdown( void );


	//! set view as if viewing a doll from front side
	virtual void 	SetDollView(	irr::scene::ISceneNode * poNode, 	// irrlicht scene node
									irr::f32 f32HeightOffs,				// height offset
									BOOL bEnableDollRotate );			// if true then rotate selected node
	//! set size of screen
	virtual void 	SetScreenSize( int iScnSizeX, int iScnSizeY );
	//! update aspect ratio
	virtual void	UpdateViewportAspect( int sx, int sy );

	//! update obit camera rotation and pitch based on the mouse
	virtual void	HandleMouseMotion( F32 f32X, F32 f32Y );
	//! update obit camera target and position
	virtual void	UpdateCamera( const irr::core::vector3df& v3fTarget );


	//! called if camera moved or look at changed
	virtual void	OnCamMoved( void )	{};

};
